<?php

	
	/**
	 * @see Bike_Initial
	 */
	require_once 'Bike/Initial.php';
	
	/**
	 * @see Bike_Controller_Router_Handler_Interface
	 */
	require_once 'Bike/Controller/Router/Handler/Interface.php';
	
	
	class Bike_Area extends Bike_Initial implements Bike_Controller_Router_Handler_Interface
	{
		const DEFAULT_AREA = 'front';
		const DEFAULT_ADMIN_ACCESSOR = 'admin';
		const MAPPER_CLASS = 'Bike_Model_Mapper_Area';

		static protected $_instance;

		protected $_name;
		protected $_default = self::DEFAULT_AREA;
		protected $_accessorDelimiter = '/';
		protected $_area;
		protected $_accessors;
		protected $_areas;

		static public function getInstance()
		{
			if(is_null(self::$_instance))
			{
				self::$_instance = new self();
			}
			return self::$_instance;
		}

		public function getName()
		{
			return $this->_name;
		}

		public function setName($Name)
		{
			$this->_name = $Name;
			return $this;
		}

		public function setDefault($Area)
		{			$this->_default = $Area;
			return $this;
		}

		public function getDefault()
		{
			return $this->_default;
		}

		public function getAccessorDelimiter()
		{
			return $this->_accessorDelimiter;
		}

		public function setAccessorDelimiter($AccessorDelimiter)
		{
			$this->_accessorDelimiter = $AccessorDelimiter;
			return $this;
		}

		public function getAccessorWithDelimiter($Accessor)
		{
			if(substr($Accessor, 0, strlen($this->getAccessorDelimiter())) != $this->getAccessorDelimiter())
        	{
        		$Accessor = $this->getAccessorDelimiter().$Accessor;
        	}
        	return $Accessor;
		}

		public function getRouteParam()
		{
			return array($this->getName() => $this->getValue());
		}

		public function isDefaultArea()
	    {	    	return ($this->getArea() == $this->getDefault());
	    }

		public function getArea()
		{			return is_null($this->_area) ? $this->getDefault() : $this->_area;
		}

		public function setArea($Area)
		{
			$this->_area = $Area;
			return $this;
		}

		public function setAccessors($Accessors=array())
		{			$this->_accessors = array_merge(array('admin' => self::DEFAULT_ADMIN_ACCESSOR), (array) @$Accessors);
			return $this;
		}

		public function getAccessors($Area=null)
		{
			if(is_null($this->_accessors))
			{				$this->setAccessors();
			}
			if(!is_null($Area))
			{				if(!isset($this->_accessors[$Area]))
				{					Throw new Bike_Controller_Router_Handler_Exception('Undefined area "'.$Area.'"');
				}
				return $this->_accessors[$Area];
			}
			return (array) $this->_accessors;
		}

		public function getAccessor($Area)
		{
			$accessors = $this->getAccessors();
			if(!isset($accessors[$Area]))
			{
				Throw new Bike_Controller_Router_Handler_Exception('Undefined area "'.$Area.'"');
			}
			return $accessors[$Area];
		}

		public function route(Zend_Controller_Request_Abstract $Request)
		{         	$pathInfo = $Request->getPathInfo();
        	$this->setArea($this->getDefault());
        	foreach($this->getAccessors() as $area => $accessor)
        	{
	        	$accessor = $this->getAccessorWithDelimiter($accessor);
	        	$len = strlen($accessor);
	        	if(substr($pathInfo, 0, $len) == $accessor)
	        	{
	        		$this->setArea($area);
	        		break;
	        	}
        	}
        	if($this->getArea() != $this->getDefault())
        	{
	        	$Accessor = $this->getAccessorWithDelimiter($this->getAccessors($this->getArea()));
	        	$Request->setPathInfo(substr($pathInfo, strlen($Accessor)));
        	}
        	return $this->getRouteParam();
		}

		public function getValue()
		{
			return $this->getArea();
		}

		public function assemble(array $Params)
		{
			$Value = $this->getArea();
			if(isset($Params[$this->getName()]))
			{
				$Value = $Params[$this->getName()];
			}

			try
			{
				return $this->getAccessor($Value);
			}
			catch(Bike_Controller_Router_Handler_Exception $e)
			{
			}
		}

		protected function isArea($Area)
	    {
	    	$area = Bike_String::factory($Area)->lowerCaseFirst();
	    	return (bool) ($this->getArea() == $area);
	    }

	    public function getAreas()
	    {	    	if(is_null($this->_areas))
	    	{	    		$this->_areas = call_user_func(array(self::MAPPER_CLASS, 'getInstance'))->fetchAll();
	    	}
	    	return $this->_areas;
	    }

	    public function getAreaId($Area=null)
	    {	    	if(is_null($Area))
	    	{	    		$Area = $this->getArea();
	    	}
	    	$area = Bike_String::factory($Area)->lowerCaseFirst();
	    	return $this->getAreas()->getRowByCode($area)->getAreaId();
	    }

	    public function __call($Method, $Args)
	    {	    	if(preg_match('/^is([\w\d]+)Area$/', $Method, $matches))
	    	{
                return $this->isArea($matches[1]);
	    	}
	    	elseif(preg_match('/^get([\w\d]+)AreaId$/', $Method, $matches))
	    	{
                return $this->getAreaId($matches[1]);
	    	}
	    	return parent::__call($Method, $Args);
	    }

		public function __toString()
		{			if(!$this->isDefaultArea())
			{
				return $this->getAccessors($this->getArea());
			}
		}
	}
